import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:hospitable_rental/models/general_type.dart';
import 'package:hospitable_rental/utils/common_toast.dart';
import 'package:hospitable_rental/utils/config.dart';
import 'package:hospitable_rental/utils/store.dart';
import 'package:hospitable_rental/viewmodels/city_viewmodel.dart';
import 'package:hospitable_rental/widgets/common_image.dart';
import 'package:city_pickers/city_pickers.dart';
import 'package:provider/provider.dart';

class SearchBar extends StatefulWidget {
  final bool showLocation; // 展示位置按钮
  final VoidCallback? goBackCallback; // 回退按钮回调函数
  final String? inputValue; // 搜索框输入值
  final String? defaultInputValue; // 搜索框默认值
  final VoidCallback? onCancel; // 取消按钮回调函数
  final bool showMap; // 展示地图按钮
  final VoidCallback? onSearch; // 用户点击搜索框触发
  final ValueChanged<String>? onSearchSubmit; // 用户输入搜索词后，点击搜索触发

  const SearchBar({
    Key? key,
    this.showLocation = false,
    this.goBackCallback,
    this.inputValue,
    this.defaultInputValue = "请输入搜索词",
    this.onCancel,
    this.showMap = false,
    this.onSearch,
    this.onSearchSubmit,
  }) : super(key: key);

  @override
  _SearchBarState createState() => _SearchBarState();
}

class _SearchBarState extends State<SearchBar> {
  String _searchWord = "";
  late TextEditingController _controller;
  late FocusNode _focusNode;

  void _onClear() {
    _controller.clear();
    setState(() {
      _searchWord = "";
    });
  }

  _saveCity(GeneralType city) async {
    if (null == city.name) return;

    context.read<CityViewModel>().city = city;

    Store store = await Store.getInstance();
    var cityString = jsonEncode(city.toJson());
    store.setString(StoreKey.city, cityString);
  }

  _changeLocation() async {
    var result = await CityPickers.showCitiesSelector(
      context: context,
      theme: ThemeData(primaryColor: Theme.of(context).primaryColor),
    );
    var cityName = result?.cityName;

    if (null == cityName) return;

    var city = Config.availableCitys.firstWhere(
      (city) => cityName.startsWith(city.name!),
      orElse: () {
        CommonToast.showToast("该城市暂未开通");
        return GeneralType.empty();
      },
    );

    _saveCity(city);
  }

  _getCity() async {
    Store store = await Store.getInstance();
    var cityString = await store.getString(StoreKey.city);
    if (null == cityString) return;

    var city = GeneralType.fromJson(jsonDecode(cityString));
    context.read<CityViewModel>().city = city;
  }

  @override
  void initState() {
    _focusNode = FocusNode();
    _controller = TextEditingController(text: widget.inputValue);
    super.initState();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    var city = context.watch<CityViewModel>().city;
    if (null == city.name) {
      city = Config.availableCitys.first;
      _getCity();
    }

    return Container(
      child: Row(
        children: [
          if (widget.showLocation) _getLocationWidget(),
          if (widget.goBackCallback != null) _getGoBackWidget(),
          _getTextFieldWidget(),
          if (widget.onCancel != null) _getCancelWidget(),
          if (widget.showMap) _getMapWidget(),
        ],
      ),
    );
  }

  Widget _getMapWidget() {
    return GestureDetector(
      onTap: () {},
      child: CommonImage(
        "assets/icons/widget_search_bar_map.png",
        width: 20.0,
      ),
    );
  }

  Widget _getCancelWidget() {
    return GestureDetector(
      onTap: widget.onCancel,
      child: Padding(
        padding: const EdgeInsets.only(right: 10.0),
        child: Text(
          "取消",
          style: TextStyle(
            color: Colors.black,
            fontSize: 14.0,
            fontWeight: FontWeight.w500,
          ),
        ),
      ),
    );
  }

  Widget _getTextFieldWidget() {
    return Expanded(
      child: Container(
        margin: EdgeInsets.only(right: 10.0),
        height: 34.0,
        decoration: BoxDecoration(
          color: Colors.grey.shade200,
          borderRadius: BorderRadius.all(Radius.circular(17.0)),
        ),
        child: TextField(
          focusNode: _focusNode,
          onTap: () {
            if (widget.onSearchSubmit == null) {
              _focusNode.unfocus();
            }
            widget.onSearch!();
          },
          onSubmitted: widget.onSearchSubmit,
          onChanged: (value) => setState(() => _searchWord = value),
          controller: _controller,
          decoration: InputDecoration(
            border: InputBorder.none,
            labelStyle: TextStyle(fontSize: 14.0, color: Colors.black),
            hintText: widget.defaultInputValue,
            hintStyle: TextStyle(fontSize: 14.0, color: Colors.grey),
            contentPadding: EdgeInsets.only(top: .5, left: -12.0),
            icon: Padding(
              padding: const EdgeInsets.only(left: 8.0, top: 2.0),
              child: Icon(
                Icons.search,
                color: Colors.grey,
                size: 18.0,
              ),
            ),
            suffixIcon: GestureDetector(
              onTap: _onClear,
              child: Icon(
                Icons.clear,
                color: _searchWord.isEmpty ? Colors.grey.shade200 : Colors.grey,
                size: 18.0,
              ),
            ),
          ),
          textInputAction: TextInputAction.search,
        ),
      ),
    );
  }

  Widget _getGoBackWidget() {
    return GestureDetector(
      onTap: widget.goBackCallback,
      child: Icon(
        Icons.chevron_left,
        color: Colors.black87,
      ),
    );
  }

  Widget _getLocationWidget() {
    return Padding(
      padding: const EdgeInsets.only(right: 8.0),
      child: GestureDetector(
        onTap: _changeLocation,
        child: Row(
          children: [
            Icon(
              Icons.room,
              color: Colors.green,
              size: 16.0,
            ),
            Text(
              context.read<CityViewModel>().city.name.toString(),
              style: TextStyle(color: Colors.black, fontSize: 14.0),
            ),
          ],
        ),
      ),
    );
  }
}
